using UnityEngine;
using System;
using System.Collections.Generic;
using System.Linq;




#if UNITY_EDITOR
using UnityEditor;
using System.Reflection;
#endif

namespace ScreenAdapter
{
    [Serializable]
    public abstract class ScreenRatioPure
    {
        public abstract Vector2 AspectRatio();
    }
    [Serializable]
    public class ScreenRatioDesign_1700x750 : ScreenRatioPure
    {
        public override Vector2 AspectRatio()
        {
            return new Vector2(1600, 750);
        }
    }
    [Serializable]
    public class ScreenRatioDesign_750x1700: ScreenRatioPure
    {
        public override Vector2 AspectRatio()
        {
            return new Vector2(750, 1600);
        }
    }
    [Serializable]
    public class ScreenRatioDesign_1920x1080: ScreenRatioPure
    {
        public override Vector2 AspectRatio()
        {
            return new Vector2(1920, 1080);
        }
    }

    /// <summary>
    /// 屏幕适配组件基类
    /// </summary>
    public abstract class AspectRatioAdapter : MonoBehaviour
    {
        [SerializeField] bool automaticAdapte = true;
        /// <summary>
        /// 用于记录不同屏幕比，适配数据的结构类
        /// </summary>
        [Serializable]
        public class Config
        {
            public Vector2 ratio;
            public float AspectRatio
            {
                get
                {
                    return ratio.x / ratio.y;
                }
            }
        }
        /// <summary>
        /// 不同屏幕适配数据列表
        /// </summary>
        public abstract Config[] Configs
        {
            get;
            set;
        }

        protected virtual void Start()
        {
            if (automaticAdapte)
            {
                SetRatio((float)Screen.width / (float)Screen.height);
            }
        }
        /// <summary>
        /// 根据传入的屏幕比，进行适配
        /// </summary>
        /// <param name="aspectRatio"></param>
        public virtual void SetRatio(float aspectRatio)
        {
            Config temp = GetSuitableConf(aspectRatio);

            if (temp != null)
            {
                OnConfigUsed(temp);
            }
        }
        /// <summary>
        /// 根据当前屏幕比获取最合适的适配数据
        /// </summary>
        /// <param name="screeRatio"></param>
        /// <returns></returns>
        public Config GetSuitableConf(float screeRatio)
        {
            Config temp = null;
            for (int i = 0; i < Configs.Length; i++)
            {
                if (temp == null || Mathf.Abs(screeRatio - temp.AspectRatio) > Mathf.Abs(screeRatio - Configs[i].AspectRatio))
                {
                    temp = Configs[i];
                }
            }
            return temp;
        }
        /// <summary>
        /// 适配数据应用到对应物体或组件上
        /// </summary>
        /// <param name="config"></param>
        abstract protected void OnConfigUsed(Config config);
        public abstract Config CreateConfig();

#if UNITY_EDITOR
        //适配当前选中物体下的所有物体
        [MenuItem("GameObject/Adapter/AdapteScrreen/All", false, priority = -100)]
        static void AdapteScrreenAll()
        {
            GameObject[] selectedGameObjects = Selection.gameObjects;
            var adapters = selectedGameObjects[0].GetComponentsInChildren<AspectRatioAdapter>();
            List<UnityEngine.Object> UndoObjs = new List<UnityEngine.Object>();
            for (int i = 0; i < adapters.Length; i++)
            {
                UndoObjs.AddRange(adapters[i].GetComponents<Component>());
            }
            Undo.RecordObjects(UndoObjs.ToArray(), "AdapteScrreenAll");
            foreach (var item in adapters)
            {
                // 标记对象为已修改
                EditorUtility.SetDirty(item.gameObject);
                item.SetRatio(AspectRatioAdapterAddtion.screenSize.x
                    / AspectRatioAdapterAddtion.screenSize.y);
            }
        }
        //适配当前选中物体
        [MenuItem("GameObject/Adapter/AdapteScrreen/root", false, priority = -100)]
        static void AdapteScrreenRoot()
        {
            GameObject[] selectedGameObjects = Selection.gameObjects;
            var root = selectedGameObjects[0].GetComponent<AspectRatioAdapter>();
            Undo.RecordObjects(root.GetComponents<Component>(), "AdapteScrreenRoot");
            if (root != null)
            {
                root.SetRatio(AspectRatioAdapterAddtion.screenSize.x
                    / AspectRatioAdapterAddtion.screenSize.y);
                EditorUtility.SetDirty(root.gameObject);
            }

        }
        //保存当前选中以及所有子物体现在的状态到配置中
        [MenuItem("GameObject/Adapter/SaveAdaptors", false, priority = -100)]
        static void SaveAdaptors()
        {
            GameObject[] selectedGameObjects = Selection.gameObjects;
            var adapters = selectedGameObjects[0].GetComponentsInChildren<AspectRatioAdapter>();
            Undo.RecordObjects(adapters, "SaveAdaptors");
            foreach (var item in adapters)
            {
                item.SaveCurrentAdaptorData();
                // 标记对象为已修改
                EditorUtility.SetDirty(item);
            }

        }
        //存档当前配置信息
        public virtual void SaveCurrentAdaptorData()
        {
            if (Configs != null && Configs.Length > 0)
            {
                Config temp = GetSuitableConf(AspectRatioAdapterAddtion.screenSize.x
                    / AspectRatioAdapterAddtion.screenSize.y);
                if (temp != null)
                {
                    OnSaveCurrentStatus(temp);
                }
            }
        }
#endif
        /// <summary>
        /// 交给子类实现如何保存当前状态
        /// </summary>
        /// <param name="config"></param>
        protected abstract void OnSaveCurrentStatus(Config config);

    }
    public abstract class AspectRatioAdapterUGUI : AspectRatioAdapter
    {
        //当组件被挂载时候
        protected virtual void Reset()
        {
            if (screenRect == null)
            {
                screenRect = this.GetComponent<RectTransform>();
            }
#if UNITY_EDITOR
            EditorUtility.SetDirty(this);
#endif
        }
        public RectTransform screenRect;
#if UNITY_EDITOR
        public override void SaveCurrentAdaptorData()
        {
            if (screenRect == null)
            {
                screenRect = this.GetComponent<RectTransform>();
            }
            base.SaveCurrentAdaptorData();
        }
#endif

    }
#if UNITY_EDITOR
    /// <summary>
    /// 屏幕适配组件辅助类
    /// </summary>
    [CustomEditor(typeof(AspectRatioAdapter), true)]
    public class AspectRatioAdapterAddtion : Editor
    {
        List<Type> subclassTypes;
        void OnEnable()
        {
            subclassTypes = GetAllSubclassNames<ScreenRatioPure>();
            foreach (var name in subclassTypes)
            {
                Debug.Log("Subclass: " + name);
            }
        }
        public override void OnInspectorGUI()
        {

            // 绘制默认的Inspector面板内容
            DrawDefaultInspector();
            PingObject();
        }
        public static List<Type> GetAllSubclassNames<T>()
        {
            return Assembly.GetAssembly(typeof(T))
                           .GetTypes()
                           .Where(t => t.IsSubclassOf(typeof(T)) && !t.IsAbstract).ToList();
        }
        // 存储每个子类是否被选中
        private Dictionary<string, bool> selectionStates = new Dictionary<string, bool>();
        bool foldOut=false;
        private void PingObject()
        {
            AspectRatioAdapter yourScript = (AspectRatioAdapter)target;

            GUILayout.Space(10);
            GUILayout.BeginHorizontal();
            // GUILayout.Label("创建Config预设（可多选）", EditorStyles.boldLabel);
            foldOut = EditorGUILayout.Foldout(foldOut, "选择Config预设（可多选）", true);

            if (GUILayout.Button("创建"))
            {
                CreateConfig();
            }
            GUILayout.EndHorizontal();
            foreach (var type in subclassTypes)
            {
                if (!selectionStates.ContainsKey(type.Name))
                {
                    selectionStates[type.Name] = true;
                }
            }
            if (foldOut)
            {

                EditorGUI.BeginChangeCheck();
                // 遍历显示 Toggle
                foreach (var type in subclassTypes)
                {
                    if (!selectionStates.ContainsKey(type.Name))
                    {
                        selectionStates[type.Name] = false;
                    }

                    selectionStates[type.Name] = EditorGUILayout.ToggleLeft(
                        type.Name, selectionStates[type.Name]);
                }

                if (EditorGUI.EndChangeCheck())
                {
                    // 你可以在这里保存结果或处理变化
                    var selected = selectionStates
                        .Where(kv => kv.Value)
                        .Select(kv => kv.Key)
                        .ToList();

                    Debug.Log("选中的类型: " + string.Join(", ", selected));
                }

            }


            GUILayout.BeginHorizontal();
            GUILayout.Label("自动填入当前适配");

            if (GUILayout.Button(new GUIContent("执行") ))
            {
                Undo.RecordObject(yourScript, "执行");
                yourScript.SaveCurrentAdaptorData();
                // // 标记对象为已修改
                EditorUtility.SetDirty(yourScript);
            }
            GUILayout.EndHorizontal();
        }
        static int mSizeFrame = -1;
        static System.Reflection.MethodInfo s_GetSizeOfMainGameView;
        static Vector2 mGameSize = Vector2.one;

        /// <summary>
        /// Size of the game view cannot be retrieved from Screen.width and Screen.height when the game view is hidden.
        /// </summary>
        public static Vector2 screenSize
        {
            get
            {
                int frame = Time.frameCount;

                if (mSizeFrame != frame || !Application.isPlaying)
                {
                    mSizeFrame = frame;

                    if (s_GetSizeOfMainGameView == null)
                    {
                        System.Type type = System.Type.GetType("UnityEditor.GameView,UnityEditor");
                        s_GetSizeOfMainGameView = type.GetMethod("GetSizeOfMainGameView",
                            System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
                    }
                    mGameSize = (Vector2)s_GetSizeOfMainGameView.Invoke(null, null);
                }
                return mGameSize;
            }
        }

        void CreateConfig()
        {
            AspectRatioAdapter yourScript = (AspectRatioAdapter)target;
            //反射访问yourScript Configs 属性
            var type = yourScript.GetType();
            // var configsField = type.GetProperty("Configs", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);


            // 获取旧数组
            var oldArray = yourScript.Configs;
            int oldLength = oldArray != null ? oldArray.Length : 0;
            // 先把旧的 ratio 值收集起来用于去重
            var existingRatios = new HashSet<Vector2>();
            if (oldArray != null)
            {
                foreach (var item in oldArray)
                {
                    var cfg = item as AspectRatioAdapter.Config;
                    if (cfg != null)
                    {
                        existingRatios.Add(cfg.ratio);
                    }
                }
            }


            //生成propertyType 类型的arr,自定义长度
            var typeSeclects = subclassTypes.Where(t => selectionStates[t.Name]).ToList();

            // 临时列表，收集不重复的 Config
            var newConfigs = new List<object>();

            for (int i = 0; i < typeSeclects.Count; i++)
            {
                var selectType = typeSeclects[i];

                var screenRatioPure = (ScreenRatioPure)Activator.CreateInstance(selectType);
                var ratio = screenRatioPure.AspectRatio();

                // 如果已有 ratio，跳过
                if (existingRatios.Contains(ratio))
                {
                    Debug.Log($"跳过重复 ratio: {ratio}");
                    continue;
                }
                existingRatios.Add(ratio);
                // 创建新 config 并添加
                var newConfig = Activator.CreateInstance(yourScript.CreateConfig().GetType()) as AspectRatioAdapter.Config;
                newConfig.ratio = ratio;

                newConfigs.Add(newConfig);
            }

            // 如果没有新内容就直接返回
            if (newConfigs.Count == 0)
            {
                Debug.Log("无新增 Config，全部为重复 ratio");
                return;
            }

            // 构建新数组：旧的 + 新的
            int finalLength = oldLength + newConfigs.Count;
            var newArr = new AspectRatioAdapter.Config[finalLength];

            // 拷贝旧数据
            if (oldArray != null)
            {
                Array.Copy(oldArray, newArr, oldLength);
            }

            // 添加新数据
            for (int i = 0; i < newConfigs.Count; i++)
            {
                newArr.SetValue(newConfigs[i], oldLength + i);
            }

            try
            {
                // 更新字段
                yourScript.Configs = newArr;
                Debug.Log($"成功增量添加 {newConfigs.Count} 个 Config");
                EditorUtility.SetDirty(yourScript);
            }
            catch (Exception ex)
            {
                Debug.LogError($"设置 Configs 属性时出错: {ex.Message}");
            }
        }

    }

#endif
}
